内部类定义:将一个类的定义放在另一个类的定义内部。
注意:内部类和组合是完全不同的概念,这一点很重要。
10.1、创建内部类
public class Parcel1 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
// Using inner classes looks just like
// using any other class, within Parcel1:
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmania");
}
} /* Output:
Tasmania
*///:~
在ship()方法里面使用内部类的时候,与使用普通方法没有什么区别。
//: innerclasses/Parcel2.java
// Returning a reference to an inner class.
public class Parcel2 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Destination to(String s) {
return new Destination(s);
}
public Contents contents() {
return new Contents();
}
public void ship(String dest) {
Contents c = contents();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tasmania");
Parcel2 q = new Parcel2();
// Defining references to inner classes:
Parcel2.Contents c = q.contents();
Parcel2.Destination d = q.to("Borneo");
}
} /* Output:
Tasmania
*///:~
在外部类的非静态方法之外的任意位置创建某个内部类对象,必须使用 OutterClassName.InnerClassName。
10.2、链接到外部类
当生成一个内部类的对象时,此对象与制造它的外部对象之间就有了一种联系,所以它能访问外围对象的所有成员,而不需要任何特殊条件。
//: innerclasses/Sequence.java
// Holds a sequence of Objects.
interface Selector {
boolean end();
Object current();
void next();
}
public class Sequence {
private Object[] items;
private int next = 0;
public Sequence(int size) { items = new Object[size]; }
public void add(Object x) {
if(next < items.length)
items[next++] = x;
}
private class SequenceSelector implements Selector {
private int i = 0;
public boolean end() { return i == items.length; }
public Object current() { return items[i]; }
public void next() { if(i < items.length) i++; }
}
public Selector selector() {
return new SequenceSelector();
}
public static void main(String[] args) {
Sequence sequence = new Sequence(10);
for(int i = 0; i < 10; i++)
sequence.add(Integer.toString(i));
Selector selector = sequence.selector();
while(!selector.end()) {
System.out.print(selector.current() + " ");
selector.next();
}
}
} /* Output:
0 1 2 3 4 5 6 7 8 9
*///:~
由上例可知,内部类自动拥有对其外围类所有成员的访问权。当某个外围类的对象创建一个内部类对象时,此类部类对象必定会秘密地捕获一个指向那个外围类的对象的引用。
10.3、使用.this与.new
如果需要生成外部类对象引用,可以使用外部类的名字后面紧跟圆点和this。这样产生的引用自动地具有正确的类型,这一点在编译期就知晓并受到检查,因此没有任何运动时开销。
//: innerclasses/DotThis.java
// Qualifying access to the outer-class object.
public class DotThis {
void f() { System.out.println("DotThis.f()"); }
public class Inner {
public DotThis outer() {
return DotThis.this;
// A plain "this" would be Inner's "this"
}
}
public Inner inner() { return new Inner(); }
public static void main(String[] args) {
DotThis dt = new DotThis();
DotThis.Inner dti = dt.inner();
dti.outer().f();
}
} /* Output:
DotThis.f()
*///:~